package cn.zhentao.util;

import cn.zhentao.config.DashScopeConfig;
import cn.zhentao.config.DashScopeTimeoutConfig;
import com.alibaba.dashscope.app.Application;
import com.alibaba.dashscope.app.ApplicationParam;
import com.alibaba.dashscope.app.ApplicationResult;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.*;

/**
 * 优化的AI调用工具类
 * 包含超时控制、重试机制和性能监控
 */
@Slf4j
@Component
public class OptimizedAiCaller {

    @Autowired
    private DashScopeConfig dashScopeConfig;

    // 创建线程池用于超时控制
    private final ExecutorService executorService = Executors.newFixedThreadPool(5);

    /**
     * 带超时控制的AI调用
     */
    public AiCallResult callWithTimeout(String prompt) {
        long startTime = System.currentTimeMillis();
        
        try {
            // 获取超时配置
            DashScopeTimeoutConfig timeoutConfig = dashScopeConfig.getTimeout();
            long timeoutMs = timeoutConfig != null ? timeoutConfig.getCall() : 60000; // 默认60秒
            
            // 创建Future任务
            Future<AiCallResult> future = executorService.submit(() -> {
                try {
                    return callAI(prompt);
                } catch (Exception e) {
                    return new AiCallResult(false, null, e.getMessage(), 0);
                }
            });
            
            // 等待结果，带超时控制
            try {
                AiCallResult result = future.get(timeoutMs, TimeUnit.MILLISECONDS);
                long endTime = System.currentTimeMillis();
                result.setDuration(endTime - startTime);
                
                log.info("AI调用成功，耗时: {}ms", result.getDuration());
                return result;
                
            } catch (TimeoutException e) {
                future.cancel(true); // 取消任务
                long endTime = System.currentTimeMillis();
                log.error("AI调用超时，耗时: {}ms", endTime - startTime);
                return new AiCallResult(false, null, "AI调用超时，请稍后重试", endTime - startTime);
                
            } catch (InterruptedException | ExecutionException e) {
                long endTime = System.currentTimeMillis();
                log.error("AI调用异常，耗时: {}ms, 错误: {}", endTime - startTime, e.getMessage());
                return new AiCallResult(false, null, "AI调用异常: " + e.getMessage(), endTime - startTime);
            }
            
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.error("AI调用失败，耗时: {}ms, 错误: {}", endTime - startTime, e.getMessage());
            return new AiCallResult(false, null, "AI调用失败: " + e.getMessage(), endTime - startTime);
        }
    }

    /**
     * 带重试机制的AI调用
     */
    public AiCallResult callWithRetry(String prompt, int maxRetries) {
        int retryCount = 0;
        Exception lastException = null;
        
        while (retryCount < maxRetries) {
            try {
                AiCallResult result = callWithTimeout(prompt);
                if (result.isSuccess()) {
                    return result;
                }
                
                // 如果不是超时错误，直接返回
                if (!result.getErrorMessage().contains("超时")) {
                    return result;
                }
                
                retryCount++;
                if (retryCount < maxRetries) {
                    log.warn("AI调用超时，第{}次重试...", retryCount);
                    Thread.sleep(1000 * retryCount); // 递增延迟
                }
                
            } catch (Exception e) {
                lastException = e;
                retryCount++;
                if (retryCount < maxRetries) {
                    log.warn("AI调用异常，第{}次重试...", retryCount);
                    try {
                        Thread.sleep(1000 * retryCount);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
        }
        
        log.error("AI调用重试{}次后仍然失败", maxRetries);
        return new AiCallResult(false, null, 
            "AI调用重试" + maxRetries + "次后仍然失败: " + 
            (lastException != null ? lastException.getMessage() : "未知错误"), 0);
    }

    /**
     * 核心AI调用方法
     */
    private AiCallResult callAI(String prompt) throws ApiException, NoApiKeyException, InputRequiredException {
        log.info("开始调用AI，用户输入: {}", prompt);
        
        ApplicationParam param = ApplicationParam.builder()
                .apiKey(dashScopeConfig.getApiKey())
                .appId(dashScopeConfig.getAppId())
                .prompt(prompt)
                .build();

        log.info("AI参数构建完成，App ID: {}", dashScopeConfig.getAppId());
        
        Application application = new Application();
        ApplicationResult result = application.call(param);
        
        String aiResponse = result.getOutput().getText();
        log.info("AI返回结果: {}", aiResponse);
        
        // 检查AI返回的内容是否为空
        if (aiResponse == null || aiResponse.trim().isEmpty()) {
            log.warn("AI返回内容为空");
            return new AiCallResult(false, null, "AI返回内容为空", 0);
        }
        
        return new AiCallResult(true, aiResponse, null, 0);
    }

    /**
     * AI调用结果类
     */
    public static class AiCallResult {
        private boolean success;
        private String response;
        private String errorMessage;
        private long duration; // 耗时（毫秒）

        public AiCallResult(boolean success, String response, String errorMessage, long duration) {
            this.success = success;
            this.response = response;
            this.errorMessage = errorMessage;
            this.duration = duration;
        }

        // Getters and Setters
        public boolean isSuccess() { return success; }
        public void setSuccess(boolean success) { this.success = success; }
        
        public String getResponse() { return response; }
        public void setResponse(String response) { this.response = response; }
        
        public String getErrorMessage() { return errorMessage; }
        public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
        
        public long getDuration() { return duration; }
        public void setDuration(long duration) { this.duration = duration; }
    }
} 